package cn.wolfcode.p2p.base.service.impl;

import cn.wolfcode.p2p.base.VerifyCode;
import cn.wolfcode.p2p.base.domain.LoginInfo;
import cn.wolfcode.p2p.base.exception.DisplayableException;
import cn.wolfcode.p2p.base.mapper.LoginInfoMapper;
import cn.wolfcode.p2p.base.service.ILoginInfoService;
import cn.wolfcode.p2p.base.service.ISendVerifyCodeService;
import cn.wolfcode.p2p.base.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.UUID;

@Service
@Transactional//事务注解管理
public class SendVerifyCodeServiceImpl implements ISendVerifyCodeService {

    @Value("${msg.msgUrl}")
    private String msgUrl;

    @Value("${msg.uid}")
    private String uid;

    @Value("${msg.key}")
    private String key;

    @Override
    public void sendVerifyCode(String phoneNumber) {
        //判断之前的是否有发送过短信或者发送短信是否大于90s才会执行循环里面的方法
        VerifyCode vo = UserContext.getVerifyCode();
        if(vo == null || DateUtil.getTimeBetwwen(new Date(),vo.getSendTime()) > 90){
            //1.生产验证码
            String randomCode = UUID.randomUUID().toString().substring(0, 4);
            //2.执行短信的发送
            StringBuilder msg = new StringBuilder(50);

            msg.append("这是您的验证码:").append(randomCode).append(",有效期为").
                    append(Constants.VERIFYCODE_VAILD_TIME).append("分钟,请尽快使用");

            //打印下验证码
            System.out.println(msg);

            //创建一个对象
            vo = new VerifyCode();

            //发送真正的短信
            try {
                //没有短信了 直接靠打印出来算了
                //sendRealMsg(phoneNumber,msg.toString());

                //3.把手机号码 验证码 发送时间保存到session中
                vo.setPhoneNumber(phoneNumber);
                vo.setRandomCode(randomCode);
                vo.setSendTime(new Date());
            } catch (Exception e) {
                e.printStackTrace();
            }
            UserContext.setVerifCode(vo);
        }else {
            throw new DisplayableException("发送验证码时间间隔太频繁,请稍后再试!");
        }
    }

    /**
     * 发送短信 并且链接api接口
     * @param phoneNumber   手机号码
     * @param context       短信内容
     */
    private void sendRealMsg(String phoneNumber, String context) throws Exception {
        //定义需要访问的地址
        URL url = new URL(msgUrl);
        //建立链接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求的方式
        conn.setRequestMethod("GET");
        //需要拼接的参数
        StringBuilder param = new StringBuilder(50);
        param.append("Uid=").append(uid)
                .append("&Key=").append(key)
                .append("&smsMob=").append(phoneNumber)
                .append("&smsText=").append(context);
        //我们需要输出内容 默认值为false 表示没有参数需要输出
        conn.setDoOutput(true);
        System.out.println(uid);
        //往对方服务器写出数据
        conn.getOutputStream().write(param.toString().getBytes("UTF-8"));
        //请求链接
        conn.connect();
        String respStr = StreamUtils.copyToString(conn.getInputStream(), Charset.forName("UTF-8"));
        int respCode = Integer.parseInt(respStr);
        if (respCode < 0){
            System.out.println("错误码: " + respCode);
            throw new DisplayableException("短信发送异常,请联系管理员");
        }
    }

    @Override
    public boolean validate(String username, String verifyCode) {
        //从session中拿到其验证对象的信息出来
        VerifyCode vo = UserContext.getVerifyCode();
        if(vo != null && // 之前发送过短信验证的
                username.equals(vo.getPhoneNumber()) && //传进来的用户名和存入session中用户名相同
                verifyCode.equals(vo.getRandomCode()) &&   //传进来的验证码需要和session中的验证码相同
                DateUtil.getTimeBetwwen(vo.getSendTime(),new Date()) <= Constants.VERIFYCODE_VAILD_TIME * 60) //当前时间和发送时间之间没有超过三分钟
        {
            return true;
        }
        return false;
    }
}
